package main

import (
	"chapter-03-mutual_auth/service"
	"context"
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/grpclog"
	"io/ioutil"
	"log"
	"net"
	"os"
	"path"
)

type server struct {
	service.UnimplementedSayHelloServer
}

func (*server) SayHello(ctx context.Context, req *service.HelloRequest) (*service.HelloResponse, error) {
	marshal, _ := json.Marshal(req)
	log.Println("收到Grpc请求,args", string(marshal))
	return &service.HelloResponse{
		Name: "yangchao",
		Age:  "18",
	}, nil
}

const (
	// Address gRPC服务地址
	Address = "127.0.0.1:9090"
)

func main() {

	//获取当前目录
	dir, err := os.Getwd()
	if err != nil {
		grpclog.Fatalf("Failed to get current directory: %v", err)
	}
	// TLS认证
	//从证书相关文件中读取和解析信息，得到证书公钥、密钥对
	cert, _ := tls.LoadX509KeyPair(path.Join(dir, "/key/server.pem"), path.Join(dir, "/key/server.key"))
	//初始化一个CertPool
	certPool := x509.NewCertPool()
	ca, _ := ioutil.ReadFile(path.Join(dir, "/key/ca.pem"))
	//注意这里只能解析pem类型的根证书，所以需要的是ca.pem
	//解析传入的证书，解析成功会将其加到池子中
	certPool.AppendCertsFromPEM(ca)

	//构建基于TLS的TransportCredentials选项
	creds := credentials.NewTLS(&tls.Config{
		Certificates: []tls.Certificate{cert},        //服务端证书链，可以有多个
		ClientAuth:   tls.RequireAndVerifyClientCert, //要求必须验证客户端证书
		ClientCAs:    certPool,                       //设置根证书的集合，校验方式使用 ClientAuth 中设定的模式
	})

	//1、创建服务，并开启TLS认证
	//ser := grpc.NewServer()
	//ser := grpc.NewServer(grpc.Creds(creds), grpc.KeepaliveParams(keepalive.ServerParameters{
	//	MaxConnectionIdle: 5 * time.Minute, //这个连接最大的空闲时间，超过就释放，解决proxy等到网络问题（不通知grpc的client和server）
	//}))
	grpcServer := grpc.NewServer(grpc.Creds(creds))

	listen, err := net.Listen("tcp", Address)
	if err != nil {
		panic(err)
	}

	service.RegisterSayHelloServer(grpcServer, &server{})
	log.Println("grpc 服务启动中")
	err = grpcServer.Serve(listen)
	if err != nil {
		panic(err)
	}
}
